package jannex;

import jannex.internal.NullDataSource;
import jannex.mapping.Mapping;
import jannex.sql.extensions.DataSourceImpl;
import jannex.mapping.MappingContext;
import jannex.mapping.ResultSetHandler;
import jannex.query.QueryBuilder;
import jannex.sql.JxConnection;
import jannex.sql.JxDataSource;
import jannex.sql.JxDatabaseMetaData;
import jannex.sql.Query;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.util.Map;
import java.util.logging.Logger;

public class Jannex implements JxDataSource {

    public static Jannex STANDALONE = new JannexBuilder(new NullDataSource()).statelessMapping(true).build();
	
	private final JxDataSource dataSource;
	private final MappingContext mappingContext;
    private final String password;
    private final String username;
    private JxDatabaseMetaData metaData;

    private final Map<String, Class<?>> typeMap;


    Jannex(DataSource dataSource, String username, String password, MappingContext mappingContext, Map<String, Class<?>> typeMap) {
        this.dataSource = new DataSourceImpl(dataSource, this);
        this.username = username;
        this.password = password;
        this.mappingContext = mappingContext;
        this.typeMap = typeMap;
    }

    @Override
    public Query query(String sql) {
        return dataSource.query(sql);
    }

    @Override
    public <E> QueryBuilder<E> queryBuilder(Class<E> elementClass) {
        return dataSource.queryBuilder(elementClass);
    }

    @Override
    public <E> QueryBuilder<E> queryBuilder(ResultSetHandler<E> handler) {
        return dataSource.queryBuilder(handler);
    }

    @Override
    public JxConnection getConnection() {
        JxConnection connection;
        if (username != null) {
            connection = dataSource.getConnection(username, password);
        } else {
            connection = dataSource.getConnection();
        }
        if (typeMap != null) {
            connection.setTypeMap(typeMap);
        }
        return connection;
    }

    @Override
    public JxConnection getConnection(String username, String password) {
        return dataSource.getConnection(username, password);
    }

    @Override
    public JxDatabaseMetaData getCachedMetaData() {
        return dataSource.getCachedMetaData();
    }

    @Override
    public JxDatabaseMetaData getMetaData() {
        return dataSource.getMetaData();
    }

    @Override
    public PrintWriter getLogWriter() {
        return dataSource.getLogWriter();
    }

    @Override
    public void setLogWriter(PrintWriter out) {
        dataSource.setLogWriter(out);
    }

    @Override
    public void setLoginTimeout(int seconds) {
        dataSource.setLoginTimeout(seconds);
    }

    @Override
    public int getLoginTimeout() {
        return dataSource.getLoginTimeout();
    }

    @Override
    public Logger getParentLogger() {
        return dataSource.getParentLogger();
    }

    @Override
    public <T> T unwrap(Class<T> iface) {
        return dataSource.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) {
        return dataSource.isWrapperFor(iface);
    }

    public <E> ResultSetHandler<E> getHandler(Class<E> elementClass) {
        return mappingContext.getHandler(elementClass);
    }

    public <E> Mapping<E> getMapping(Class<E> elementClass) {
        return mappingContext.getMapping(elementClass);
    }

    public MappingContext getMappingContext() {
        return mappingContext;
    }
}
